package auto.app.service.impl;

import auto.app.controller.from.BeforeAssertion.BeforeAssertionChickFrom;
import auto.app.controller.from.BeforeAssertion.BeforeAssertionFrom;
import auto.app.controller.from.BeforeAssertion.BeforeAssertionUpdateFrom;
import auto.app.controller.info.BeforeAssertion.BeforeAssertionChickInfo;
import auto.app.enums.AssertMethodsType;
import auto.app.enums.ResultMethodsTpye;
import auto.app.exetion.MainExection;
import auto.app.model.BeforeAssertion;
import auto.app.dao.BeforeAssertionDao;
import auto.app.model.CaseInterface;
import auto.app.service.BeforeAssertionService;
import auto.app.service.CaseService;
import auto.app.util.CommonUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.function.Consumer;

import static auto.app.enums.ResultMethodsTpye.*;
import static auto.app.exetion.MainExetionMessage.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 杨森
 * @since 2022-08-31
 */
@Service
@Slf4j
public class BeforeAssertionServiceImpl extends ServiceImpl<BeforeAssertionDao, BeforeAssertion> implements BeforeAssertionService {
    @Autowired
    private CaseService caseService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean beforeAssertionAdd(BeforeAssertionFrom beforeAssertionFrom) throws MainExection {
        //判断测试用例是否存在
        CaseInterface caseServiceById = caseService.getById(beforeAssertionFrom.getCaseId());
        if (caseServiceById == null) {
            throw new MainExection(CASEERROR.getCode(), CASEERROR.getMsg());
        }
        Integer continueExtraction = beforeAssertionFrom.getContinueExtraction();
        if (continueExtraction == 1) {
            if (!(beforeAssertionFrom.getAutomaticIndex() >= 0)) {
                throw new MainExection(BEFOREASSERTIONINSERTERROR.getCode(), BEFOREASSERTIONINSERTERROR.getMsg());
            }
        }
        BeforeAssertion beforeAssertion = CommonUtil.copyOne(beforeAssertionFrom, BeforeAssertion.class);
        beforeAssertion.setCreateTime(LocalDateTime.now());
        int insert = baseMapper.insert(beforeAssertion);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean beforeAssertionUpdate(BeforeAssertionUpdateFrom beforeAssertionUpdateFrom) throws MainExection {
        //判断测试用例是否存在
        CaseInterface caseServiceById = caseService.getById(beforeAssertionUpdateFrom.getCaseId());
        if (caseServiceById == null) {
            throw new MainExection(CASEERROR.getCode(), CASEERROR.getMsg());
        }
        //判断断言id是否存在
        BeforeAssertion beforeAssertion = baseMapper.selectById(beforeAssertionUpdateFrom.getAutomaticId());
        if (beforeAssertion == null) {
            throw new MainExection(BEFOREASSERTIONSELECTERROR.getCode(), BEFOREASSERTIONSELECTERROR.getMsg());
        }
        BeforeAssertion beforeAssertionUpdate = CommonUtil.copyOne(beforeAssertionUpdateFrom, BeforeAssertion.class);
        beforeAssertionUpdate.setUpdateTime(LocalDateTime.now());
        int i = baseMapper.updateById(beforeAssertionUpdate);
        return true;
    }

    @Override
    public BeforeAssertion beforeAssertionDetail(Integer automaticId) throws MainExection {
        //判断断言id是否存在
        BeforeAssertion beforeAssertion = baseMapper.selectById(automaticId);
        if (beforeAssertion == null) {
            throw new MainExection(BEFOREASSERTIONSELECTERROR.getCode(), BEFOREASSERTIONSELECTERROR.getMsg());
        }
        return baseMapper.selectById(automaticId);
    }

    @Override
    public List<BeforeAssertion> beforeAssertionList(Integer caseId) throws MainExection {
        //判断测试用例是否存在
        CaseInterface caseServiceById = caseService.getById(caseId);
        if (caseServiceById == null) {
            throw new MainExection(CASEERROR.getCode(), CASEERROR.getMsg());
        }
        LambdaQueryWrapper<BeforeAssertion> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(BeforeAssertion::getCaseId, caseId);
        return baseMapper.selectList(lambdaQueryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean beforeAssertionDelete(Integer automaticId) throws MainExection {
        //判断断言id是否存在
        BeforeAssertion beforeAssertion = baseMapper.selectById(automaticId);
        if (beforeAssertion == null) {
            throw new MainExection(BEFOREASSERTIONSELECTERROR.getCode(), BEFOREASSERTIONSELECTERROR.getMsg());
        }
        int i = baseMapper.deleteById(automaticId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<BeforeAssertionChickInfo> beforeAssertionChick(BeforeAssertionChickFrom beforeAssertionChickFrom) throws MainExection {
        //判断测试用例是否存在
        CaseInterface caseServiceById = caseService.getById(beforeAssertionChickFrom.getCaseId());
        if (caseServiceById == null) {
            throw new MainExection(CASEERROR.getCode(), CASEERROR.getMsg());
        }
        ArrayList<BeforeAssertionChickInfo> assertionChickInfos = new ArrayList<>();
        //判断是否存在启用的断言
        LambdaQueryWrapper<BeforeAssertion> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(BeforeAssertion::getCaseId, beforeAssertionChickFrom.getCaseId())
                .eq(BeforeAssertion::getAssertEnable, 0);
        List<BeforeAssertion> beforeAssertions = baseMapper.selectList(lambdaQueryWrapper);
        if (CollectionUtils.isEmpty(beforeAssertions)) {
//            BeforeAssertionChickInfo assertionChickInfo = BeforeAssertionChickInfo.builder().msg("测试用例下并无断言").result(true).build();
            return null;
        }
        //如果存在断言进行断言判断
        for (BeforeAssertion beforeAssertion : beforeAssertions) {
            BeforeAssertionChickInfo assertionChickInfo = chickJson(beforeAssertion, beforeAssertionChickFrom.getJsonString());
            assertionChickInfos.add(assertionChickInfo);
        }
        return assertionChickInfos;
    }

    /**
     * @param beforeAssertion //传入断言对象
     * @param jsonString      //json字符串
     * @return BeforeAssertionChickInfo //返回断言结果
     */
    private BeforeAssertionChickInfo chickJson(BeforeAssertion beforeAssertion, String jsonString) {
        Integer continueExtraction = beforeAssertion.getContinueExtraction();
        //是否继续提取
        if (continueExtraction == 0) {
            //提取第一个参数
            String josnValue = CommonUtil.findJosnValue(beforeAssertion.getExtractExpression(), jsonString);
            //对提取的值进行判断 为空
            if (josnValue == null && !beforeAssertion.getAssertMethods().equals("existence") && !beforeAssertion.getAssertMethods().equals("!existence")) {
                log.debug(beforeAssertion.getExtractExpression() + "在返回参数中未查询到对应匹配的值");
                return BeforeAssertionChickInfo.builder().result(false).msg(beforeAssertion.getExtractExpression() + "在返回参数中未查询到对应匹配的值").build();
            } else {
                //进行断言的方法操作
                BeforeAssertionChickInfo beforeAssertionChickInfo = chickMehtod(josnValue, beforeAssertion.getAssertMethods(), beforeAssertion.getAssertValue());
                if (beforeAssertionChickInfo != null) {
                    beforeAssertionChickInfo.setMsg(beforeAssertion.getAssertionName() + ":" + beforeAssertionChickInfo.getMsg() + ";");
                    return beforeAssertionChickInfo;
                } else {
                    return BeforeAssertionChickInfo.builder().result(false).msg("不存在对应的方法 或者 枚举类型").build();
                }
            }
        } else {
            //获取hashmap
            HashMap<Integer, String> josnValueList = CommonUtil.findJosnValueList(beforeAssertion.getExtractExpression(), jsonString);
            //根据index获取值
            String josnValue = null;
            try {
                josnValue = josnValueList.get(beforeAssertion.getAutomaticIndex());
            } catch (Exception e) {
                log.debug(e.getMessage());
                return BeforeAssertionChickInfo.builder().result(false).msg("对应下标的值不存在").build();
            }
            //对提取的值进行判断 为空
            if (josnValue == null && !beforeAssertion.getAssertMethods().equals("existence") && !beforeAssertion.getAssertMethods().equals("!existence")) {
                log.debug(beforeAssertion.getExtractExpression() + "在返回参数中未查询到对应匹配的值");
                return BeforeAssertionChickInfo.builder().result(false).msg(beforeAssertion.getExtractExpression() + "在返回参数中未查询到对应匹配的值").build();
            } else {
                //进行断言的方法操作
                BeforeAssertionChickInfo beforeAssertionChickInfo = chickMehtod(josnValue, beforeAssertion.getAssertMethods(), beforeAssertion.getAssertValue());
                if (beforeAssertionChickInfo != null) {
                    beforeAssertionChickInfo.setMsg(beforeAssertion.getAssertionName() + ":" + beforeAssertionChickInfo.getMsg() + ";");
                    return beforeAssertionChickInfo;
                } else {
                    return BeforeAssertionChickInfo.builder().result(false).msg("不存在对应的方法 或者 枚举类型").build();
                }
            }
        }

    }

    /***
     *
     * @param josnValue //提取出来的建
     * @param method //方法
     * @param assertvalue //断言值
     * @return 返回是否通过
     */
    private BeforeAssertionChickInfo chickMehtod(String josnValue, String method, String assertvalue) {
        AssertMethodsType assertMethodsType = AssertMethodsType.getByValue(method);
        if (assertMethodsType != null) {
            switch (assertMethodsType) {
                //相等方法
                case EQ:
                    if (josnValue.equals(assertvalue)) {
                        return BeforeAssertionChickInfo.builder().result(EQTRUE.getResult()).msg(EQTRUE.getMsg()).build();
                    } else {
                        return BeforeAssertionChickInfo.builder().result(EQFALSE.getResult()).msg(EQFALSE.getMsg()).build();
                    }
                    //不相等方法
                case NOEQ:
                    if (!josnValue.equals(assertvalue)) {
                        return BeforeAssertionChickInfo.builder().result(NOEQTRUE.getResult()).msg(NOEQTRUE.getMsg()).build();
                    } else {
                        return BeforeAssertionChickInfo.builder().result(NOEQFALSE.getResult()).msg(NOEQFALSE.getMsg()).build();
                    }
                    //存在
                case EX:
                    if (ObjectUtil.isNotNull(josnValue)) {
                        return BeforeAssertionChickInfo.builder().result(EXTRUE.getResult()).msg(EXTRUE.getMsg()).build();
                    } else {
                        return BeforeAssertionChickInfo.builder().result(EXFALSE.getResult()).msg(EXFALSE.getMsg()).build();
                    }
                    //不存在
                case NOEX:
                    if (ObjectUtil.isNull(josnValue)) {
                        return BeforeAssertionChickInfo.builder().result(NOEXTRUE.getResult()).msg(NOEXTRUE.getMsg()).build();
                    } else {
                        return BeforeAssertionChickInfo.builder().result(NOEXFALSE.getResult()).msg(NOEXFALSE.getMsg()).build();
                    }
                    //包含
                case CONTAIN:
                    if (josnValue.contains(assertvalue)) {
                        return BeforeAssertionChickInfo.builder().result(CONTAINTRUE.getResult()).msg(CONTAINTRUE.getMsg()).build();
                    } else {
                        return BeforeAssertionChickInfo.builder().result(CONTAINFALSE.getResult()).msg(CONTAINFALSE.getMsg()).build();
                    }
                    //不包含
                case NOCONTAIN:
                    if (!josnValue.contains(assertvalue)) {
                        return BeforeAssertionChickInfo.builder().result(NOCONTAINTRUE.getResult()).msg(NOCONTAINTRUE.getMsg()).build();
                    } else {
                        return BeforeAssertionChickInfo.builder().result(NOCONTAINFALSE.getResult()).msg(NOCONTAINFALSE.getMsg()).build();
                    }
                    //为空
                case ISEMPTY:
                    if (ObjectUtil.isEmpty(josnValue)) {
                        return BeforeAssertionChickInfo.builder().result(ISEMPTYTRUE.getResult()).msg(ISEMPTYTRUE.getMsg()).build();
                    } else {
                        return BeforeAssertionChickInfo.builder().result(ISEMPTYFALSE.getResult()).msg(ISEMPTYFALSE.getMsg()).build();
                    }
                    //不为空
                case ISNOTEMPTY:
                    if (!ObjectUtil.isNotEmpty(josnValue)) {
                        return BeforeAssertionChickInfo.builder().result(ISNOTEMPTYTRUE.getResult()).msg(ISNOTEMPTYTRUE.getMsg()).build();
                    } else {
                        return BeforeAssertionChickInfo.builder().result(ISNOTEMPTYFALSE.getResult()).msg(ISNOTEMPTYFALSE.getMsg()).build();
                    }
                    //大于
                case GT:
                    if (Integer.parseInt(josnValue) > Integer.parseInt(assertvalue)) {
                        return BeforeAssertionChickInfo.builder().result(GTTRUE.getResult()).msg(GTTRUE.getMsg()).build();
                    } else {
                        return BeforeAssertionChickInfo.builder().result(GTFALSE.getResult()).msg(GTFALSE.getMsg()).build();
                    }
                    //大于等于
                case GTE:
                    if (Integer.parseInt(josnValue) >= Integer.parseInt(assertvalue)) {
                        return BeforeAssertionChickInfo.builder().result(GTETRUE.getResult()).msg(GTETRUE.getMsg()).build();
                    } else {
                        return BeforeAssertionChickInfo.builder().result(GTEFALSE.getResult()).msg(GTEFALSE.getMsg()).build();
                    }
                    //小于
                case LT:
                    if (Integer.parseInt(josnValue) < Integer.parseInt(assertvalue)) {
                        return BeforeAssertionChickInfo.builder().result(LTTRUE.getResult()).msg(LTTRUE.getMsg()).build();
                    } else {
                        return BeforeAssertionChickInfo.builder().result(LTFALSE.getResult()).msg(LTFALSE.getMsg()).build();
                    }
                    //小于等于
                case LTE:
                    if (Integer.parseInt(josnValue) <= Integer.parseInt(assertvalue)) {
                        return BeforeAssertionChickInfo.builder().result(LTETRUE.getResult()).msg(LTETRUE.getMsg()).build();
                    } else {
                        return BeforeAssertionChickInfo.builder().result(LTEFALSE.getResult()).msg(LTEFALSE.getMsg()).build();
                    }
                default:
                    log.info("方法不匹配" + josnValue);
                    return null;
            }
        } else {
            log.info("枚举中无对应的类型");
            return null;
        }
    }

}
